﻿using System.Runtime.Serialization;
using System.Web.Script.Serialization;

namespace LaoLuo
{
    /// <summary>
    /// 
    /// </summary>
    [DataContract]
    public partial class Result : ResultBase
    {
        public Result(ResultStatus status, string message = null)
            :base(status, message)
        {
            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="status"></param>
        /// <param name="message"> </param>
        public Result(bool status = true, string message = null)
            : base(status, message)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        [DataMember]
        public object Data { get; set; }

        /*/// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static implicit operator Result<object>(Result value)
        {
            return new Result<object>
            {
                Data = value.Data,
                AllDataCount = value.AllDataCount,
                Messages = value.Messages,
                Status = value.Status
            };
        }*/

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static implicit operator Result(bool value)
        {
            return new Result(value);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static implicit operator bool(Result value)
        {
            return value.Status == ResultStatus.成功;
        }

        
    }

    public partial class Result
    {
        #region factory

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static Result NewNegativeResult()
        {
            return new Result(false);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static Result NewNoPermissionResult()
        {
            return new Result {Status = ResultStatus.无权限};
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TData"></typeparam>
        /// <returns></returns>
        public static Result<TData> NewNegativeResult<TData>()
        {
            return new Result<TData>(false);
        }

        /// <summary>
        /// 获取一个状态为失败，并包含指定message的Result
        /// </summary>
        /// <param name="format"> </param>
        /// <param name="args"> </param>
        /// <returns></returns>
        public static Result NewNegativeResult(string format, params object[] args)
        {
            var ret = NewNegativeResult();
            ret.PushMessage(format, args);
            return ret;
        }

        /// <summary>
        /// 获取一个状态为失败，并包含指定message的Result
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        /// <typeparam name="TData"></typeparam>
        /// <returns></returns>
        public static Result<TData> NewNegativeResult<TData>(string format, params object[] args)
        {
            var ret = NewNegativeResult<TData>();
            ret.PushMessage(format, args);
            return ret;
        }

        /*/// <summary>
        /// gets a <see cref="Result"/> with status <see cref="ResultStatus.无权限"/>
        /// </summary>
        /// <returns></returns>
        public static Result NewNoPermissionResult()
        {
            return new Result(ResultStatus.无权限, null, "请登录以进行此操作");
        }*/

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static Result NewPositiveResult()
        {
            return new Result();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static Result NewPositiveMessageResult(params string[] messages)
        {
            var result = new Result();

            result.PushMessages(messages);

            return result;
        }

        /// <summary>
        /// gets a <see cref="ResultExtensions"/> with status <see cref="Result.ResultStatus.成功"/>, and specified <see cref="data"/> and <see cref="allDataCount"/>
        /// </summary>
        /// <param name="data"></param>
        /// <param name="allDataCount"></param>
        /// <returns></returns>
        public static Result<TData> NewPositiveResult<TData>(TData data, int allDataCount = 0)
        {
            return new Result<TData>(data) { AllDataCount = allDataCount };
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="format"></param>
        /// <param name="args"></param>
        /// <typeparam name="TData"></typeparam>
        /// <returns></returns>
        public static Result<TData> NewPositiveResult<TData>(TData data, string format, params object[] args)
        {
            var ret = new Result<TData> { Status = ResultStatus.成功, Data = data };

            ret.PushMessage(format, args);

            return ret;
        }

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [DataContract]
    public class Result<T> : Result
    {

        /// <summary>
        /// init a Result
        /// </summary>
        public Result(bool status, string message)
            : base(status, message)
        {
            Data = default(T);
        }

        /// <summary>
        /// 
        /// </summary>
        public Result()
            : this(true, null)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="status"></param>
        public Result(bool status)
            : this(status, null)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="message"></param>
        public Result(T data, string message = null)
            : this(true, message)
        {
            Data = data;
        }

        #region props

        /// <summary>
        /// 
        /// </summary>
        [IgnoreDataMember]
        [ScriptIgnore]
        public new T Data
        {
            get { return (T)base.Data; }
            set { base.Data = value; }
        }

        #endregion
    }

    /*public class DetailedResult<T> : Result<T>
    {
        public DetailedResult()
            : base(true)
        {
        }

        public void Merge<TOther>(DetailedResult<TOther> other)
        {
            Status = other.Status;
            if (other.HasError)
            {
                ErrorList.AddRange(other.ErrorList);
            }
        }

        public void Merge(DetailedResult<T> other)
        {
            Status = other.Status;
            if (other.HasError)
            {
                ErrorList.AddRange(other.ErrorList);
            }
            Data = other.Data;
        }

        public void AddError(string format, params object[] args)
        {
            AddError(new UserError(string.Format(format, args)));
        }

        public void AddError(UserError error)
        {
            ErrorList.Add(error);
            this.Fail("共有{0}条错误", ErrorList.Count);
        }

        private List<UserError> _errorList;

        public List<UserError> ErrorList
        {
            get { return _errorList ?? (_errorList = new List<UserError>()); }
        }

        public int ErrorCount
        {
            get
            {
                if (ErrorList == null)
                {
                    return 0;
                }

                return ErrorList.Count;
            }
        }

        public bool HasError
        {
            get { return ErrorCount > 0; }
        }
    }

    public class UserError
    {
        public UserError(string message)
        {
            Message = message;
        }

        public string Message { get; set; }
    }*/
}
